package e310

import (
	"encoding/binary"
	"errors"
	"gitee.com/alex_li/uhf"
	"github.com/lishimeng/go-log"
)

func (c *Client) SetPower(power int) (success bool, err error) {

	var dbm = power * 100
	bs := make([]byte, 2)
	binary.BigEndian.PutUint16(bs, uint16(dbm))

	packet := GenPacket(CmdPowerSet, PacketTypeReq, bs...)
	err = c.sendPacket(packet, func(packet Packet) {
		data := packet.ParameterData
		success = data[0] == 0x00
	})
	return
}

func (c *Client) Select(params uhf.SelectParam) (code byte, err error) {
	bs := params.Marshal()
	packet := GenPacket(CmdSelect, PacketTypeReq, bs...)
	err = c.sendPacket(packet, func(packet Packet) {
		data := packet.ParameterData
		code = data[0]
	})
	return
}

func (c *Client) SetSelectMode(mode uhf.SelectMode) (success bool, err error) {

	packet := GenPacket(CmdSelectMode, PacketTypeReq, byte(mode))

	err = c.sendPacket(packet, func(packet Packet) {
		data := packet.ParameterData
		success = data[0] == 0x00
	})
	return
}

func (c *Client) Read(operation uhf.MemoryOperation, startPtr int, payload []byte) (code byte, err error) {

	return
}

type writeParam struct {
	Password []byte
	Bank     uhf.MemBank
	Sa       int
	Payload  []byte
}

func (wp *writeParam) Marshal() (data []byte) {
	data = append(data, wp.Password...)
	data = append(data, byte(wp.Bank))
	data = append(data, 0x00, byte(wp.Sa))
	payloadLen := len(wp.Payload) / 2
	data = append(data, 0x00, byte(payloadLen))
	data = append(data, wp.Payload...)
	return
}

func (c *Client) Write(operation uhf.MemoryOperation, startPtr int, payload []byte) (code byte, err error) {

	if len(operation.Mask) > 0 {
		code, err = c.Select(uhf.SelectParam{
			SelParam: uhf.SelParam{
				Target:  uhf.SessionS0,
				Action:  0,
				MemBank: uhf.BankEpc,
			},
			StartPtr: 0x02,
			Mask:     operation.Mask,
		})
		if err != nil {
			log.Info("select fail")
			log.Info(err)
			return
		}
		if code != 0x00 {
			log.Info("select error no: %02x", code)
			return
		}
	}
	wp := writeParam{
		Password: operation.Password,
		Bank:     operation.Bank,
		Sa:       startPtr,
		Payload:  payload,
	}
	params := wp.Marshal()
	packet := GenPacket(CmdWrite, PacketTypeReq, params...)
	err = c.sendPacket(packet, func(packet Packet) {
		data := packet.ParameterData
		code = data[0]
	})
	return
}

func (c *Client) Lock(bank uhf.MemBank, lockType uhf.LockType, password []byte) (code byte, err error) {
	ld := uhf.LockParam{}
	switch bank {
	case uhf.BankEpc:
		ld.LockMask.EpcMash = lockType
		ld.LockAction.EpcAction = lockType
	case uhf.BankTid:
		ld.LockMask.TidMask = lockType
		ld.LockAction.TidAction = lockType
	case uhf.BankUser:
		ld.LockMask.UserMask = lockType
		ld.LockAction.UserAction = lockType
	}
	ld.Password = password
	params := ld.Marshal()
	packet := GenPacket(CmdLock, PacketTypeReq, params...)
	err = c.sendPacket(packet, func(packet Packet) {
		data := packet.ParameterData
		code = data[0]
	})
	return
}

func (c *Client) InventoryOnce(onTag func(pc, epc []byte, rssi byte)) (code byte, err error) {
	log.Info("cmd inventory once...")
	packet := GenPacket(CmdInvOnce, PacketTypeReq, 0x00)
	var list []Packet
	c.notifyListener = func(packet Packet) {
		log.Info("save tag")
		list = append(list, packet)
	}
	err = c.sendPacket(packet, func(packet Packet) {
		data := packet.ParameterData
		code = data[0]
	})
	//if err == nil { // 无标签
	//	return
	//}
	if errors.Is(err, TimeoutErr) {
		err = nil
	}
	if onTag != nil && len(list) > 0 {
		//for _, p := range list {
		//	tagCallback(p, onTag)
		//}
		tagCallback(list[0], onTag)
	}
	return
}
